/* BEGIN_COMMON_COPYRIGHT_HEADER
 * (c)LGPL2+
 *
 * Copyright: 2011 Razor team
 *            2014 LXQt team
 * Authors:
 *   Alexander Sokoloff <sokoloff.a@gmail.com>
 *   Maciej Płaza <plaza.maciej@gmail.com>
 *   Kuzma Shapran <kuzma.shapran@gmail.com>
 *
 * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. *
 *
 * This program or library is free software; you can redistribute it
 * and/or modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA
 *
 * END_COMMON_COPYRIGHT_HEADER */

#include "ukuigrouppopup.h"
#include <QEnterEvent>
#include <QDrag>
#include <QMimeData>
#include <QLayout>
#include <QPainter>
#include <QStyleOption>
#include <QDebug>
#include <QApplication>
#include <QScreen>

#include <QtX11Extras/QX11Info>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <KWindowEffects>
#include "common/common.h"

#define OPENGL               "gl2"
#define XRENDER              "xrender"
#define UKUI_KWIN_SERVICE    "org.ukui.KWin"
#define UKUI_KWIN_PATH       "/Compositor"
#define UKUI_KWIN_INTERFACE  "org.ukui.kwin.Compositing"
#define COMPOSITING_TYPE     "compositingType"

QPixmap qimageFromXImage(XImage* ximage)
{
    QImage::Format format = QImage::Format_ARGB32_Premultiplied;
    if (ximage->depth == 24) {
        format = QImage::Format_RGB32;
    } else if (ximage->depth == 16) {
        format = QImage::Format_RGB16;
    }

    QImage image = QImage(reinterpret_cast<uchar*>(ximage->data),
                          ximage->width, ximage->height,
                          ximage->bytes_per_line, format).copy();

    // 大端还是小端?
    if ((QSysInfo::ByteOrder == QSysInfo::LittleEndian && ximage->byte_order == MSBFirst)
            || (QSysInfo::ByteOrder == QSysInfo::BigEndian && ximage->byte_order == LSBFirst)) {

        for (int i = 0; i < image.height(); i++) {
            if (ximage->depth == 16) {
                ushort* p = reinterpret_cast<ushort*>(image.scanLine(i));
                ushort* end = p + image.width();
                while (p < end) {
                    *p = ((*p << 8) & 0xff00) | ((*p >> 8) & 0x00ff);
                    p++;
                }
            } else {
                uint* p = reinterpret_cast<uint*>(image.scanLine(i));
                uint* end = p + image.width();
                while (p < end) {
                    *p = ((*p << 24) & 0xff000000) | ((*p << 8) & 0x00ff0000)
                         | ((*p >> 8) & 0x0000ff00) | ((*p >> 24) & 0x000000ff);
                    p++;
                }
            }
        }
    }

    // 修复alpha通道
    if (format == QImage::Format_RGB32) {
        QRgb* p = reinterpret_cast<QRgb*>(image.bits());
        for (int y = 0; y < ximage->height; ++y) {
            for (int x = 0; x < ximage->width; ++x)
                p[x] |= 0xff000000;
            p += ximage->bytes_per_line / 4;
        }
    }
    return QPixmap::fromImage(image);
}

/************************************************
    this class is just a container of window buttons
    the main purpose is showing window buttons in
    vertical layout and drag&drop feature inside
    group
 ************************************************/
UKUIGroupPopup::UKUIGroupPopup(UKUITaskGroup *group):
    QFrame(group),
    m_group(group)
{
    Q_ASSERT(group);
    setAcceptDrops(true);
    setWindowFlags(Qt::FramelessWindowHint | Qt::ToolTip);
    setAttribute(Qt::WA_AlwaysShowToolTips);
    setAttribute(Qt::WA_TranslucentBackground);
    setProperty("useSystemStyleBlur", true);
    QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    setSizePolicy(sizePolicy);

    setLayout(new QHBoxLayout);
    layout()->setSpacing(3);
    layout()->setMargin(0);
    m_rightclick = false;

    connect(&m_closeTimer, &QTimer::timeout, this, &UKUIGroupPopup::closeTimerSlot);
    m_closeTimer.setSingleShot(true);
    m_closeTimer.setInterval(400);
    setMaximumWidth(QApplication::screens().at(0)->size().width());
    setMaximumHeight(QApplication::screens().at(0)->size().height());

    m_interface = new QDBusInterface(UKUI_KWIN_SERVICE,
                                     UKUI_KWIN_PATH,
                                     UKUI_KWIN_INTERFACE,
                                     QDBusConnection::sessionBus());
    if (m_interface->isValid()) {
        QString compositingType = m_interface->property(COMPOSITING_TYPE).toString();
        if (compositingType == OPENGL) {
            m_isXrender = false;
        } else if (compositingType == XRENDER) {
            m_isXrender = true;
        }
    }

//    //监听主题改变，更新图标
    const QByteArray id_Theme(ORG_UKUI_STYLE);
    if (QGSettings::isSchemaInstalled(id_Theme)) {
        m_changeTheme = new QGSettings(id_Theme);
    } else {
        qWarning() << "Icon Theme GSettings isn't Installed";
        return;
    }
    connect(m_changeTheme, &QGSettings::changed, this, [=] (const QString &key) {
        if (key == STYLE_NAME_KEY_ICONTHEME) {
            for (auto it= m_widgetHash.begin(); it != m_widgetHash.end();it++) {
                UKUITaskWidget *taskwidget = it.value();
                taskwidget->updateSdkIcon();
            }
        }
    });
}

UKUIGroupPopup::~UKUIGroupPopup()
{
}

void UKUIGroupPopup::dragEnterEvent(QDragEnterEvent *event)
{
    event->accept();
    QWidget::dragEnterEvent(event);
}

void UKUIGroupPopup::dragLeaveEvent(QDragLeaveEvent *event)
{
    hide(false/*not fast*/);
    QFrame::dragLeaveEvent(event);
}

/************************************************
 *
 ************************************************/
void UKUIGroupPopup::leaveEvent(QEvent *event)
{
    if (!m_rightclick) {
        QTimer::singleShot(300, this,SLOT(closeWindowDelay()));
        m_rightclick = false;
    } else {
        m_rightclick = false;
    }
}

/************************************************
 *
 ************************************************/
void UKUIGroupPopup::enterEvent(QEvent *event)
{
    QTimer::singleShot(300, this,SLOT(killTimerDelay()));
//    m_closeTimer.stop();
}

void UKUIGroupPopup::killTimerDelay()
{
      m_closeTimer.stop();
}

void UKUIGroupPopup::closeWindowDelay()
{
    if (m_closeTimer.isActive()) {
        m_closeTimer.stop();
    }
    if (this->geometry().contains(QCursor::pos())) {
        return;
    }
    close();
    sendCloseSigToKWin();

}

void UKUIGroupPopup::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::RightButton) {
        m_rightclick = true;
    } else {
        m_rightclick = false;
    }
}

void UKUIGroupPopup::paintEvent(QPaintEvent *event)
{
    QPainter p(this);
    QStyleOption opt;
    opt.initFrom(this);
    p.setBrush(QBrush(QColor(0xff,0x14,0x14,0xb2)));
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}

void UKUIGroupPopup::hide(bool fast)
{
    if (fast && !this->geometry().contains(QCursor::pos())) {
        close();
    }
    else if (!this->geometry().contains(QCursor::pos())) {
        m_closeTimer.start();
    }
}

void UKUIGroupPopup::show()
{
    m_closeTimer.stop();
    QFrame::show();
}

void UKUIGroupPopup::setKeepShow(bool flag)
{
    isKeepShow = true;
}

void UKUIGroupPopup::setKeepLeave(bool flag)
{
    if (!this->geometry().contains(QCursor::pos())) {
        isKeepShow = false;
        m_closeTimer.start();
    }
}

void UKUIGroupPopup::closeTimerSlot()
{
    bool button_has_dnd_hover = false;
    QLayout* l = layout();
    for (int i = 0; l->count() > i; ++i) {
        UKUITaskWidget const * const button = dynamic_cast<UKUITaskWidget const *>(l->itemAt(i)->widget());
        if (0 != button && button->hasDragAndDropHover()) {
            button_has_dnd_hover = true;
            break;
        }
    }
    if (!button_has_dnd_hover && !this->geometry().contains(QCursor::pos())) {
        close();
    }
    sendCloseSigToKWin();
}

void UKUIGroupPopup::sendCloseSigToKWin()
{
    QDBusMessage message = QDBusMessage::createSignal("/", "com.ukui.kwin", "panelNotUpdateLayer");
    QList<QVariant> args;
    bool flag = true;
    args.append(flag);
    message.setArguments(args);
    QDBusConnection::sessionBus().send(message);
}

void UKUIGroupPopup::addWindow(const WindowId& id,UKUITaskBar *bar)
{
    qint32 window = id.toInt();
    UKUITaskWidget *taskwidget = new UKUITaskWidget(window, bar, this);
    m_useOpenGL = taskwidget->canUseOpenGL();
    m_widgetHash.insert(window,taskwidget);
    taskwidget->setFixedSize(PREVIEW_WINDOW_WIDTH, PREVIEW_WINDOW_HEIGHT);
    if (m_group->plugin()->panel()->isHorizontal()) {
        m_allWidgetWidth += PREVIEW_WINDOW_WIDTH;
        this->setFixedSize(QSize(m_allWidgetWidth, this->height()));
    } else {
        m_allWidgetHeight += PREVIEW_WINDOW_HEIGHT;
        this->setFixedSize(QSize(this->width(), m_allWidgetHeight));
    }

    connect(taskwidget, &UKUITaskWidget::windowActived, [this]{
        close();
    });
    //this->addTaskWidget(taskwidget);

}

void UKUIGroupPopup::onWindowRemoved(const WindowId& id)
{
    qint32 window = id.toInt();
    UKUITaskWidget *taskwidget = m_widgetHash.value(window);
    QSize widgetsize = taskwidget->size();
    m_widgetHash.remove(window);
    this->removeWidget(taskwidget);
    taskwidget->deleteLater();

    if(m_group->plugin()->panel()->isHorizontal()) {
        m_allWidgetWidth -= widgetsize.width();
    } else {
        m_allWidgetHeight -= widgetsize.height();
    }

    if(m_isShowByList) {
        int winWidth = LIST_WINDOW_WIDTH;
        int winheight = LIST_WINDOW_HEIGHT;
        this->setFixedSize(winWidth,  winheight * m_group->visibleSdkButtonsCount());
        caculatePopupWidgetPos();
    } else {
        if(m_group->plugin()->panel()->isHorizontal()) {
            this->setFixedSize(QSize(m_allWidgetWidth, this->height()));
        } else {
            this->setFixedSize(QSize(this->width(), m_allWidgetHeight));
        }
    }

}

void UKUIGroupPopup::onWindowChanged(const WindowId& id)
{
//    if (prop.testFlag(NET::WMIcon) || prop2.testFlag(NET::WM2WindowClass)){
        for (auto it= m_widgetHash.begin(); it != m_widgetHash.end();it++) {
            UKUITaskWidget *taskwidget = it.value();
            taskwidget->updateSdkIcon();
        }
//    }

}

void UKUIGroupPopup::caculateTaskWidget()
{
    int winWidth = PREVIEW_WINDOW_WIDTH;
    int winHeight = PREVIEW_WINDOW_HEIGHT;
    int totalLenth = 0;

    int title_width = 0;

    /*caculate each taskwidget-image's width*/
    XImage *img = NULL;
    Display *display = NULL;
    QPixmap thumbnail;
    XWindowAttributes attr;

    for (UKUISdkTaskWidgetHash::const_iterator it = m_widgetHash.begin(); it != m_widgetHash.end(); it++) {
        bool visible = KWindowInfo(it.key(), NET::WMDesktop).isOnDesktop(KWindowSystem::currentDesktop());
        UKUITaskWidget *taskwidget = it.value();
        taskwidget->setVisible(visible);
        taskwidget->setParent(this);
        connect(taskwidget, &UKUITaskWidget::closeSigtoPop, [this] { this->pubcloseWindowDelay(); });
        //connect(taskwidget, &UKUITaskWidget::closeSigtoGroup, [this] { closeGroup(); });
        taskwidget->addThumbNail();
        display = XOpenDisplay(nullptr);
        XGetWindowAttributes(display, it.key(), &attr);
        img = XGetImage(display, it.key(), 0, 0, attr.width, attr.height, 0xffffffff,ZPixmap);
        float imgWidth = 0;
        float imgHeight = 0;
        if (m_group->plugin()->panel()->isHorizontal()) {
            imgWidth = (float)attr.width / (float)attr.height * winHeight;
            imgHeight = winHeight;
            if (imgWidth > PREVIEW_WINDOW_WIDTH) {
                imgWidth = PREVIEW_WINDOW_WIDTH;
            }
            if(taskwidget->isVisibleTo(this)) {
                totalLenth += (int)imgWidth;
            }
            taskwidget->setThumbMaximumSize(MAX_SIZE_OF_Thumb);
            taskwidget->setThumbScale(true);
        } else {
            imgWidth = winWidth;
            imgHeight = (float)attr.height / (float)attr.width * winWidth;
            if ((int)imgHeight > PREVIEW_WINDOW_HEIGHT) {
                imgHeight = PREVIEW_WINDOW_HEIGHT;
            }
            if(taskwidget->isVisibleTo(this)) {
                totalLenth += (int)imgHeight;
            }
            taskwidget->setThumbMaximumSize(MAX_SIZE_OF_Thumb);
            taskwidget->setThumbScale(true);
        }
        if (img) {
            thumbnail = qimageFromXImage(img).scaled((int)imgWidth, (int)imgHeight, Qt::KeepAspectRatio,Qt::SmoothTransformation);
        } else {
            qDebug()<<"can not catch picture";
            QPixmap pxmp;
            if (pxmp.load(QString("/tmp/%1.png").arg(it.key()))) {
                thumbnail = pxmp.scaled((int)imgWidth, (int)imgHeight, Qt::KeepAspectRatio,Qt::SmoothTransformation);
            } else {
                thumbnail = QPixmap((int)imgWidth, (int)imgHeight);
                thumbnail.fill(QColor(0, 0, 0, 127));
            }
        }
        taskwidget->setThumbNail(thumbnail);
        taskwidget->updateTitle();
        taskwidget->setFixedSize((int)imgWidth, (int)imgHeight);
        title_width = taskwidget->width() - 75;
        taskwidget->setTitleFixedWidth(title_width);
        m_widget->layout()->setContentsMargins(0,0,0,0);
        m_widget->layout()->setSpacing(8);
        if(taskwidget->isVisibleTo(this)) {
            m_widget->layout()->addWidget(taskwidget);
        }
        if (img) {
            XDestroyImage(img);
        }
        if (display) {
            XCloseDisplay(display);
        }
    }

    if (m_group->plugin()->panel()->isHorizontal()) {
        m_allWidgetWidth = totalLenth;
        this->setFixedSize(QSize(totalLenth, winHeight));
    } else {
        m_allWidgetHeight = totalLenth;
        this->setFixedSize(QSize(winWidth, totalLenth));
    }
}

void UKUIGroupPopup::caculateQmlWidget()
{
    int winWidth = PREVIEW_WINDOW_WIDTH;
    int winHeight = PREVIEW_WINDOW_HEIGHT;
    int titleHeight = PREVIEW_TITLE_HEIGHT;
    int totalLenth = 0;

    int title_width = 0;

    for (UKUISdkTaskWidgetHash::const_iterator it = m_widgetHash.begin(); it != m_widgetHash.end(); it++) {
        bool visible = KWindowInfo(it.key(), NET::WMDesktop).isOnDesktop(KWindowSystem::currentDesktop());
        UKUITaskWidget *taskwidget = it.value();
        taskwidget->setVisible(visible);
        taskwidget->setParent(this);
        connect(taskwidget, &UKUITaskWidget::closeSigtoPop, [this] { this->pubcloseWindowDelay(); });
        connect(taskwidget, SIGNAL(signalKeepShow(bool)), this, SLOT(setKeepShow(bool)));
        connect(taskwidget, SIGNAL(signalKeepLeave(bool)), this, SLOT(setKeepLeave(bool)));
        float qmlWidth = 0;
        float qmlHeight = 0;
        KWindowInfo info(it.key(), NET::WMGeometry | NET::WMName);
        int appwidth = info.geometry().width();
        int appheight =info.geometry().height();
        qDebug()<<"appwidth:"<<appwidth;
        qDebug()<<"appheight:"<<appheight;
        if (m_group->plugin()->panel()->isHorizontal()) {
            qmlHeight = winHeight - titleHeight - PREVIEW_SPACEING * 2;
            qmlWidth = (float)appwidth / (float)appheight * qmlHeight;
            if (qmlWidth > PREVIEW_WINDOW_WIDTH) {
                qmlWidth = PREVIEW_WINDOW_WIDTH;
            }
        } else {
            qmlWidth = winWidth - PREVIEW_SPACEING * 2;
            qmlHeight = (float)appheight / (float)appwidth * qmlWidth;
            if ((int)qmlHeight > PREVIEW_WINDOW_HEIGHT) {
                qmlHeight = PREVIEW_WINDOW_HEIGHT;
            }
        }
        qDebug()<<"qmlWidth:"<<qmlWidth;
        qDebug()<<"qmlHeight:"<<qmlHeight;

        taskwidget->setLiveThumbNail((int)qmlWidth , (int)qmlHeight);
        taskwidget->updateTitle();
        if (m_group->plugin()->panel()->isHorizontal()) {
            taskwidget->setFixedSize(qmlWidth + PREVIEW_SPACEING * 2, winHeight);
            if(taskwidget->isVisibleTo(this)) {
                totalLenth += taskwidget->width();
            }
        } else {
            taskwidget->setFixedSize(winWidth, qmlHeight + titleHeight + PREVIEW_SPACEING * 2);
            if(taskwidget->isVisibleTo(this)) {
                totalLenth += taskwidget->height();
            }
        }
        title_width = qmlWidth - 64;
        taskwidget->setTitleFixedWidth(title_width);
        m_widget->layout()->setContentsMargins(0,0,0,0);
        m_widget->layout()->setSpacing(8);
        if (taskwidget->isVisibleTo(this)) {
            m_widget->layout()->addWidget(taskwidget);
        }
    }
    int space = (m_widget->layout()->count() - 1) * PREVIEW_SPACEING;
    if (m_group->plugin()->panel()->isHorizontal()) {
        m_allWidgetWidth = totalLenth + space;
        this->setFixedSize(QSize(totalLenth + space, winHeight - PREVIEW_SPACEING));
    } else {
        m_allWidgetHeight = totalLenth;
        this->setFixedSize(QSize(winWidth, totalLenth - PREVIEW_SPACEING));
    }
}

void UKUIGroupPopup::showPreviewMode()
{
    if (m_group->plugin()->panel()->isHorizontal()) {
        if (m_allWidgetWidth <= QApplication::screens().at(0)->size().width() && this->width() != PREVIEW_WINDOW_HEIGHT) {
            showAllWindowByThumbnail();
        } else {
            showAllWindowByList();
        }
    } else {
        if (m_allWidgetHeight <= QApplication::screens().at(0)->size().height()) {
            showAllWindowByThumbnail();
        } else {
            showAllWindowByList();
        }
    }

}

void UKUIGroupPopup::showAllWindowByList()
{
    m_isShowByList = true;
    int winWidth = LIST_WINDOW_WIDTH;
    int winheight = LIST_WINDOW_HEIGHT;
    int popWindowheight = (winheight) * (m_group->visibleSdkButtonsCount());
    int screenAvailabelHeight = QApplication::screens().at(0)->size().height() - m_group->plugin()->panel()->panelSize();
    if (!m_group->plugin()->panel()->isHorizontal()) {
        screenAvailabelHeight = QApplication::screens().at(0)->size().height();//panel is vect
    }
    if (this->layout()->count() > 0) {
        removeSrollWidget();
    }
    m_scrollArea = new QScrollArea(this);
    m_scrollArea->setWidgetResizable(true);
    m_scrollArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    this->layout()->addWidget(m_scrollArea);
    this->setFixedSize(winWidth,  popWindowheight < screenAvailabelHeight? popWindowheight : screenAvailabelHeight);
    m_widget = new QWidget(this);
    m_widget->setAttribute(Qt::WA_TranslucentBackground);
    m_widget->setLayout(new QVBoxLayout);
    m_widget->layout()->setSpacing(8);
    m_scrollArea->setWidget(m_widget);
    /*begin catch preview picture*/
    for (UKUISdkTaskWidgetHash::const_iterator it = m_widgetHash.begin();it != m_widgetHash.end();it++) {
        bool visible = KWindowInfo(it.key(), NET::WMDesktop).isOnDesktop(KWindowSystem::currentDesktop());
        UKUITaskWidget *taskwidget = it.value();
        taskwidget->setVisible(visible);
        taskwidget->clearMask();
        taskwidget->setTitleFixedWidth(m_widget->width());
        taskwidget->updateTitle();
        taskwidget->setParent(m_scrollArea);
        taskwidget->removeLiveThumbNail();
        taskwidget->removeThumbNail();
        taskwidget->adjustSize();
        taskwidget->setFixedHeight(winheight);

        connect(taskwidget, &UKUITaskWidget::closeSigtoPop, [this] { this->pubcloseWindowDelay(); });
        //connect(taskwidget, &UKUITaskWidget::closeSigtoGroup, [this] { closeGroup(); });
        if (taskwidget->isVisibleTo(this)) {
            m_widget->layout()->addWidget(taskwidget);
        }
    }
    /*end*/
    m_group->plugin()->willShowWindow(this);
    caculatePopupWidgetPos();
    this->setStyle(new CustomStyle());
    this->setFixedWidth(winWidth);
    m_scrollArea->setAttribute(Qt::WA_TranslucentBackground);
    m_scrollArea->setFrameShape(QFrame::NoFrame);
    m_scrollArea->setProperty("drawScrollBarGroove",false);
    m_scrollArea->verticalScrollBar()->setProperty("drawScrollBarGroove",false);
    m_scrollArea->show();
    this->show();
}

void UKUIGroupPopup::showAllWindowByThumbnail()
{
    m_isShowByList = false;

    if (this->layout()->count() > 0) {
        removeWidget();
    }
    m_widget = new QWidget(this);
    m_widget->setAttribute(Qt::WA_TranslucentBackground);
    if (m_group->plugin()->panel()->isHorizontal()) {
        m_widget->setLayout(new QHBoxLayout);
    } else {
        m_widget->setLayout(new QVBoxLayout);
    }

    if (m_useOpenGL && !m_isXrender) {
        caculateQmlWidget();
    } else {
        caculateTaskWidget();
    }

    m_group->plugin()->willShowWindow(this);
    this->layout()->addWidget(m_widget);
    //set preview window position
    caculatePopupWidgetPos();
    if (!this->isVisible()) {
        this->show();
    }
    setRegionBlur();
}

void UKUIGroupPopup::setRegionBlur()
{
    QRect rectall[m_widgetHash.size()];
    QRegion regionall;
    for (int i = 0; i < m_widget->layout()->count(); i++) {
        rectall[i] = m_widget->layout()->itemAt(i)->geometry();

        QPainterPath path;
        path.addRoundRect(rectall[i].x() + 2 , rectall[i].y() + 2, rectall[i].width() - 4, rectall[i].height() - 4, 12, 12);
        QPolygon polygon = path.toFillPolygon().toPolygon();//获得这个路径上的所有的点
        QRegion region(polygon);//根据这些点构造这个区域
        regionall = regionall.united(region);
    }
    KWindowEffects::enableBlurBehind(this->winId(), true, regionall);
}

void UKUIGroupPopup::removeWidget()
{
    if (m_scrollArea) {
        removeSrollWidget();
    }
    if (m_widget) {
        this->layout()->removeWidget(m_widget);
        QHBoxLayout *hLayout = dynamic_cast<QHBoxLayout*>(m_widget->layout());
        QVBoxLayout *vLayout = dynamic_cast<QVBoxLayout*>(m_widget->layout());
        if (hLayout != NULL) {
            hLayout->deleteLater();
            hLayout = NULL;
        }
        if (vLayout != NULL) {
            vLayout->deleteLater();
            vLayout = NULL;
        }
        //m_widget->setParent(NULL);
        m_widget->deleteLater();
        m_widget = NULL;
    }
}


void UKUIGroupPopup::removeSrollWidget()
{
    if (m_scrollArea) {
        this->layout()->removeWidget(m_scrollArea);
        this->layout()->removeWidget(m_scrollArea->takeWidget());
    }
    if (m_widget) {
        this->layout()->removeWidget(m_widget);
        QHBoxLayout *hLayout = dynamic_cast<QHBoxLayout*>(m_widget->layout());
        QVBoxLayout *vLayout = dynamic_cast<QVBoxLayout*>(m_widget->layout());
        if (hLayout != NULL) {
            hLayout->deleteLater();
            hLayout = NULL;
        }
        if (vLayout != NULL) {
            vLayout->deleteLater();
            vLayout = NULL;
        }
        //m_widget->setParent(NULL);
        m_widget->deleteLater();
        m_widget = NULL;
    }
    if (m_scrollArea) {
        m_scrollArea->deleteLater();
        m_scrollArea = NULL;
    }
}

void UKUIGroupPopup::caculatePopupWidgetPos()
{
    int previewPosition = 0;

    //set preview window position
    if (m_isShowByList) {
        int winWidth = 246;
        if (m_group->plugin()->panel()->isHorizontal()) {
            previewPosition =  m_group->plugin()->panel()->panelSize()/2 - winWidth/2;
            this->setGeometry(calculatePopupWindowPos(m_group->mapToGlobal(QPoint(previewPosition,0)), this->size()));
        } else {
            previewPosition = m_group->plugin()->panel()->panelSize()/2 - winWidth/2;
            this->setGeometry(calculatePopupWindowPos(m_group->mapToGlobal(QPoint(0,previewPosition)), this->size()));
        }
    } else {
        if (m_group->plugin()->panel()->isHorizontal()) {
            if (this->size().width()/2 < QCursor::pos().x()) {
                previewPosition = 0 - this->size().width()/2 + m_group->plugin()->panel()->panelSize()/2;
            } else {
                previewPosition = 0 -(QCursor::pos().x() + m_group->plugin()->panel()->panelSize()/2);
            }
            this->setGeometry(calculatePopupWindowPos(m_group->mapToGlobal(QPoint(previewPosition,0)), this->size()));
        } else {
            if (this->size().height()/2 < QCursor::pos().y()) {
                previewPosition = 0 - this->size().height()/2 + m_group->plugin()->panel()->panelSize()/2;
            } else {
                previewPosition = 0 -(QCursor::pos().y() + m_group->plugin()->panel()->panelSize()/2);
            }
            this->setGeometry(calculatePopupWindowPos(m_group->mapToGlobal(QPoint(0,previewPosition)), this->size()));
        }
    }
}

QRect UKUIGroupPopup::calculatePopupWindowPos(QPoint const & absolutePos, QSize const & windowSize) const
{
    int margin = 8;
    QRect rect = m_group->plugin()->panel()->calculatePopupWindowPos(absolutePos, windowSize);
    int x = rect.x(), y = rect.y();
    switch (m_group->plugin()->panel()->position())
    {
    case IUKUIPanel::PositionTop:
        y = rect.y() + margin;
        break;

    case IUKUIPanel::PositionBottom:
        y = rect.y() - margin;
        break;

    case IUKUIPanel::PositionLeft:
        x = rect.x() + margin;
        break;

    case IUKUIPanel::PositionRight:
        x = rect.x() - margin;
        break;
    }
    QRect res(QPoint(x, y), windowSize);
    return res;
}
